/*
 * Copyright 2021 MindMotion Microelectronics Co., Ltd.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef __HAL_GPIO_H__
#define __HAL_GPIO_H__

#include "hal_common.h"

/*!
 * @addtogroup GPIO
 * @{
 */

/*!
 * @brief GPIO maximum speed type.
 */
typedef enum
{
    GPIO_Speed_50MHz = 1u,  /*!< Maximum speed is 50MHz. */
    GPIO_Speed_20MHz = 2u,  /*!< Maximum speed is 20MHz. */
    GPIO_Speed_10MHz = 3u,  /*!< Maximum speed is 10MHz. */
} GPIO_Speed_Type;

/*!
* @brief Port input / output mode
*/
typedef enum
{
    GPIO_PinMode_In_Analog      = 0x00,  /*!< Analog input. */
    GPIO_PinMode_In_Floating    = 0x04,  /*!< Floating input. */
    GPIO_PinMode_In_PullDown    = 0x28,  /*!< Pull down input. */
    GPIO_PinMode_In_PullUp      = 0x48,  /*!< Pull up input. */
    GPIO_PinMode_Out_OpenDrain  = 0x14,  /*!< Universal open drain output. */
    GPIO_PinMode_Out_PushPull   = 0x10,  /*!< Universal push-pull output. */
    GPIO_PinMode_AF_OpenDrain   = 0x1C,  /*!< Multiplex open drain output. */
    GPIO_PinMode_AF_PushPull    = 0x18   /*!< Multiplexed push-pull output. */
} GPIO_PinMode_Type;

/*!
 * @brief This type of structure instance is used to keep the settings when calling the @ref GPIO_Init() to initialize the GPIO module.
 */
typedef struct
{
    uint16_t           Pins;    /*!< GPIO Operating pins. See to @ref GPIO_Pin */
    GPIO_Speed_Type    Speed;   /*!< GPIO pin speed mode. */
    GPIO_PinMode_Type  PinMode; /*!< GPIO pin input / output functional mode. */
} GPIO_Init_Type;


/*!
 * @addtogroup GPIO_Pin
 * @brief GPIO pin mask codes.
 * @{
 */
#define GPIO_PIN_0    (0x0001U) /*!< Pin 0 selected.    */
#define GPIO_PIN_1    (0x0002U) /*!< Pin 1 selected.    */
#define GPIO_PIN_2    (0x0004U) /*!< Pin 2 selected.    */
#define GPIO_PIN_3    (0x0008U) /*!< Pin 3 selected.    */
#define GPIO_PIN_4    (0x0010U) /*!< Pin 4 selected.    */
#define GPIO_PIN_5    (0x0020U) /*!< Pin 5 selected.    */
#define GPIO_PIN_6    (0x0040U) /*!< Pin 6 selected.    */
#define GPIO_PIN_7    (0x0080U) /*!< Pin 7 selected.    */
#define GPIO_PIN_8    (0x0100U) /*!< Pin 8 selected.    */
#define GPIO_PIN_9    (0x0200U) /*!< Pin 9 selected.    */
#define GPIO_PIN_10   (0x0400U) /*!< Pin 10 selected.   */
#define GPIO_PIN_11   (0x0800U) /*!< Pin 11 selected.   */
#define GPIO_PIN_12   (0x1000U) /*!< Pin 12 selected.   */
#define GPIO_PIN_13   (0x2000U) /*!< Pin 13 selected.   */
#define GPIO_PIN_14   (0x4000U) /*!< Pin 14 selected.   */
#define GPIO_PIN_15   (0x8000U) /*!< Pin 15 selected.   */
#define GPIO_PINS_All (0xFFFFU) /*!< All pins selected. */
/*!
 * @}
 */

/*!
 * @addtogroup GPIO_AF
 * @brief GPIO pin alternative function.
 * @{
 */
#define GPIO_AF_0     (0x00U)   /*!< Alternative function 0. */
#define GPIO_AF_1     (0x01U)   /*!< Alternative function 1. */
#define GPIO_AF_2     (0x02U)   /*!< Alternative function 2. */
#define GPIO_AF_3     (0x03U)   /*!< Alternative function 3. */
#define GPIO_AF_4     (0x04U)   /*!< Alternative function 4. */
#define GPIO_AF_5     (0x05U)   /*!< Alternative function 5. */
#define GPIO_AF_6     (0x06U)   /*!< Alternative function 6. */
#define GPIO_AF_7     (0x07U)   /*!< Alternative function 7. */
#define GPIO_AF_8     (0x08U)   /*!< Alternative function 8. */
#define GPIO_AF_9     (0x09U)   /*!< Alternative function 9. */
#define GPIO_AF_10    (0x0AU)   /*!< Alternative function 10. */
#define GPIO_AF_11    (0x0BU)   /*!< Alternative function 11. */
#define GPIO_AF_12    (0x0CU)   /*!< Alternative function 12. */
#define GPIO_AF_13    (0x0DU)   /*!< Alternative function 13. */
#define GPIO_AF_14    (0x0EU)   /*!< Alternative function 14. */
#define GPIO_AF_15    (0x0FU)   /*!< Alternative function 15. */
/*!
 * @}
 */


/*!
 * @brief Initialize the GPIO module.
 *
 * @param GPIOx GPIO instance.
 * @param init  Pointer to the initialization structure. See to @ref GPIO_Init_Type.
 * @return None.
 */
void     GPIO_Init(GPIO_Type * GPIOx, GPIO_Init_Type * init);

/*!
 * @brief Set the specified data port bit.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @return None.
 */
void     GPIO_SetBits(GPIO_Type * GPIOx, uint16_t pins);

/*!
 * @brief Clear the specified data port bit.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @return None.
 */
void     GPIO_ClearBits(GPIO_Type * GPIOx, uint16_t pins);

/*!
 * @brief Writes 0 or 1 to the specified bit.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @param val Decide whether to set or clear.
 * @return None.
 */
void     GPIO_WriteBit(GPIO_Type * GPIOx, uint16_t pins, uint16_t val);

/*!
 * @brief Write 0 or 1 for multiple IO ports.
 *
 * @param GPIOx GPIO instance.
 * @param val Decide whether to set or clear.
 * @return None.
 */
void     GPIO_WriteBits(GPIO_Type * GPIOx, uint16_t val);

/*!
 * @brief Keep the set IO configuration unchanged.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @param enable_lock enable 'true' to enable the lock, 'false' to disable the lock.
 * @return None.
 */
void     GPIO_PinLock(GPIO_Type * GPIOx, uint16_t pins, bool enable_lock);

/*!
 * @brief Lock the corresponding bit of the select port configuration register.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @return None.
 */
void     GPIO_PinLockConf(GPIO_Type * GPIOx, uint16_t pins);

/*!
 * @brief Read the value once entered before by the specified pin.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @return Status of a pin's logic level, 0 for low level or 1 for high level.
 */
bool     GPIO_ReadInDataBit(GPIO_Type * GPIOx, uint16_t pins);

/*!
 * @brief Read the value previously output by the specified pin.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @return Status of a pin's logic level, 0 for low level or 1 for high level.
 */
bool     GPIO_ReadOutDataBit(GPIO_Type * GPIOx, uint16_t pins);

/*!
 * @brief Read the specified GPIO port input.
 *
 * @param GPIOx GPIO instance.
 * @return A hexadecimal number.
 */
uint16_t GPIO_ReadInData(GPIO_Type * GPIOx);

/*!
 * @brief Read the specified GPIO port output.
 *
 * @param GPIOx GPIO instance.
 * @return A hexadecimal number.
 */
uint16_t GPIO_ReadOutData(GPIO_Type * GPIOx);

/*!
 * @brief Pin alternate function configuration of GPIO.
 *
 * @param GPIOx GPIO instance.
 * @param pins GPIO Operating pins. See to @ref GPIO_Pin.
 * @param alternate_function Reuse the unified I/O port, but the function is different.
 * @return None.
 */
void     GPIO_PinAFConf(GPIO_Type* GPIOx, uint16_t pins, uint8_t alternate_function);

/*!
 * @}
 */


#endif /* __HAL_GPIO_H__ */

